package tool.soft

import java.io.File
import akka.stream.Materializer
import command.CommandExec
import dao._
import implicits.Implicits._
import models.Tables
import models.Tables._
import org.joda.time.DateTime
import org.zeroturnaround.zip.ZipUtil
import play.api.data.FormBinding
import play.api.libs.ws.WSClient
import play.api.mvc.{AnyContent, Request}
import play.twirl.api.Html
import shared.Pojo._
import tool.Pojo._
import tool.plot.AllPlot._
import tool.plot._
import tool.soft.AllSoft.SoftBT
import tool._
import play.api.i18n.Messages
import shared.pojo.mission.KeggEnrichSoftData
import utils.Utils
import upickle.default._

/** Created by yz on 15/9/2020
  */
object KeggEnrichSoft extends KeggEnrichSoftT with SoftBT {

  override def getFileInfos(workspaceDir: File, index: Int)(implicit
      matrixFileDataDao: MatrixFileDataDao,
      messages: Messages
  ): List[FileInfoData] = {
    val resultDir = new File(workspaceDir.getParentFile, "result")
    List(
      FileInfoData("Pathway_Result.csv", messages("pathwayResult")),
      FileInfoData("Pathway_Bubbleplot.pdf", messages("pathwayBubbleplot")),
      FileInfoData("Pathway_Barplot.pdf", messages("pathwayBarplot")),
      FileInfoData("Sig_Pathways_ID.zip", messages("sigPathwaysID")),
      FileInfoData("Sig_Pathways_Name.zip", messages("sigPathwaysName"))
    ).filter { fileInfoData =>
      new File(resultDir, fileInfoData.fileName).exists()
    }
  }

  override def produceConfigFile(workspaceDir: File, index: Int)(implicit
      request: Request[AnyContent],
      formBinding: FormBinding
  ) = {
    plot.PathwayBar.initConfigFile(workspaceDir, idStr = "")
    plot.PathwayBubble.initConfigFile(workspaceDir, idStr = "")
    Utils.t2ConfigFileWithDefault(workspaceDir, data)
    Utils.t2ConfigFileWithDefault(data, Tool.getCalculateConfigJsonFile(workspaceDir))
  }

  override def getResultHtml(missionId: Int)(implicit request: Request[AnyContent], messages: Messages): Html = {
    views.html.user.mission.keggEnrichResult(missionId)
  }

  def getArg(implicit request: Request[AnyContent], messages: Messages, formBinding: FormBinding): ujson.Value = {
    val methodStr = data.method match {
      case "hyperg" => "Hypergeometric Test"
      case "fisher" => "Fisher's Exact Test"
    }
    val nodeImpStr = data.nodeImp match {
      case "rbc" => "Relative-betweeness Centrality"
      case "dgr" => "Out-degree Centrality"
    }
    val basicJson = ujson.Obj(
      messages("species") -> s"${data.species}_${data.isSmp}",
      "Over Representation Analysis" -> methodStr,
      "Pathway Topology Analysis" -> nodeImpStr
    )
    val fcJson = if (data.hasGroup) {
      val groupNum = Tool.getGroupNum(userId, data.groupFile)
      groupNum match {
        case x if x == 2 => ujson.Obj(messages("fCCalculationMethod") -> Tool.getFcMethod(data.fcMethod))
        case x => ujson.Obj()
      }
    } else {
      ujson.Obj()
    }
    basicJson ++ fcJson
  }

  override def resultDeal(workspaceDir: File, resultDir: File)(implicit
      ws: WSClient,
      materializer: Materializer
  ): Unit = {
    super.resultDeal(workspaceDir, resultDir)
    val idDir = new File(workspaceDir, "Sig_Pathways_ID")
    if (idDir.exists() && idDir.myListFiles.nonEmpty) {
      val idDestFile = new File(resultDir, "Sig_Pathways_ID.zip")
      ZipUtil.pack(idDir, idDestFile)
    }
    val nameDir = new File(workspaceDir, "Sig_Pathways_Name")
    if (nameDir.exists() && nameDir.myListFiles.nonEmpty) {
      val nameDestFile = new File(resultDir, "Sig_Pathways_Name.zip")
      ZipUtil.pack(nameDir, nameDestFile)
    }
    val needConvertFileNamePrefixs = List(
      plot.PathwayBubble.plotO.pngFileNamePrefixIn,
      plot.PathwayBar.plotO.pngFileNamePrefixIn
    )
    val convertCommands = Tool.fileConvertCommandsIfExist(workspaceDir, needConvertFileNamePrefixs)
    CommandExec().exec { b =>
      CommandData(workspace = workspaceDir, commands = convertCommands, runFileName = "image_convert.sh")
    }
  }

  override def produceInput(workspaceDir: File, resultDir: File)(implicit dao: MyDao): Unit = {
    super.produceInput(workspaceDir, resultDir)
    val rawDataFile = new File(workspaceDir, "AllMet_Raw.txt")
    Tool.produceKeggInfoFile(rawDataFile, workspaceDir)
  }

  override def getCommandData(workspaceDir: File, resultDir: File, index: Int): List[CommandData] = {
    val solutionFile = new File(Tool.dataDir, "color_solution/color_solution_1.txt")
    val groupFile = new File(workspaceDir, "group.txt")
    val command =
      s"""
         |${Tool.rScript} ${new File(Tool.rPath, "anno.R").unixPath}
         |${"Rscript".condaPath()} ${new File(Tool.rPath, "idMapping.R").unixPath} --d ${Tool.databaseDir.unixPath}
         |${"Rscript".condaPath()} ${new File(Tool.rPath, "kegg_enrich.R").unixPath} --d ${Tool.databaseDir.unixPath}
         |${"Rscript".condaPath()} ${new File(
          Tool.rPath,
          "pathway_layout_plot.R"
        ).unixPath} --d ${Tool.databaseDir.unixPath}
           """.stripMargin
    val plotCommands = List(
      plot.PathwayBar.getCommand(workspaceDir, "", convert = false),
      plot.PathwayBubble.getCommand(workspaceDir, "", convert = false)
    )
    List(CommandData(workspaceDir, List(command) ::: plotCommands))
  }

  override def getHtml(missionName: String, missionId: Option[Int])(implicit
      request: Request[AnyContent],
      messages: Messages
  ): Html = {
    views.html.user.soft.keggEnrich(missionName, missionId)
  }

  override def getMission(implicit
      request: Request[AnyContent],
      matrixFileDataDao: MatrixFileDataDao,
      messages: Messages,
      formBinding: FormBinding
  ): Tables.MissionRow = {
    val input = if (data.hasGroup) {
      List(data.file, data.groupFile)
    } else List(data.file)
    val hasLibInputs = input
    val argJson = getArg
    MissionRow(
      id = 0,
      missionName = s"${data.missionName}",
      kind = nameStr,
      userId = userId,
      startTime = new DateTime(),
      state = "preparing",
      arg = argJson,
      input = hasLibInputs
    )
  }

  override def produceInputFile(
      workspaceDir: File
  )(implicit request: Request[AnyContent], dao: MyDao, formBinding: FormBinding): Any = {
    val rawDataFile = new File(workspaceDir, "AllMet_Raw.txt")
    Tool.produceRawMetaboliteFile(userId, data.file, rawDataFile)
    val groupFile = new File(workspaceDir, "group.txt")
    if (data.hasGroup) {
      Tool.produceRawGroupFile(userId, data.groupFile, rawDataFile, groupFile)
    } else {
      Tool.produceNoGroupFile(rawDataFile, groupFile)
    }
  }

  override def data(implicit request: Request[AnyContent], formBinding: FormBinding) = {
    Tool.transformRq.transform(reader[KeggEnrichSoftData])
  }

}
